//
//  ST_PushDailyCoordinator.swift
//  btvideo
//
//  Created by mac on 2020/7/23.
//  Copyright © 2020 JarvanZhang. All rights reserved.
//

import UIKit
import SwifterSwift
import RealmSwift
import SwiftyJSON
import SDWebImage
import RxCocoa
import RxSwift


class ST_PushDailyCoordinator: NSObject {

    

    //    MARK: - Init
    static let shared = ST_PushDailyCoordinator()
    
    private var timer:Timer!
    
    private var current_task_i_d:String?
    
    fileprivate lazy var progress_view = ST_PushDailyProgressView()
    
    private override init() {
        super.init()
        
        binding()
        
        timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(task_loop), userInfo: nil, repeats: true)
        
    }
    
    var disposeBag = DisposeBag()
    
    ///布局
    var layout_behavior = BehaviorRelay<UIView?>(value: nil)
    
    private func binding(){
        
        layout_behavior.compactMap{ $0 }.subscribe(onNext: { v in
            
            if v != self.progress_view.superview{
                v.addSubview(self.progress_view)
                self.progress_view.snp.makeConstraints { (make) in
                    make.left.equalToSuperview().offset(32)
                    make.right.equalToSuperview().offset(-32)
                    make.bottom.equalToSuperview().offset(iPhoneXSeries ? -24-49-BTSafeAreaBottom : -24-49)
                    make.height.equalTo(ST_PushDailyProgressView.fwHeight)
                }
                self.progress_view.isHidden = true
            }
            
        }).disposed(by: disposeBag)
        
    }
    
    
    @objc func task_loop(){
            
        guard let account = ST_BTUserInfoManager.shared.current_account_info else { return  }
        
        if current_task_i_d != nil{ return }
        
        let realm = try! Realm()
        
//        1. 先查询出需要恢复上传的数据 where 【uploadingTaskID == nil ，数据库 是 uploading】
        let resumeTask = realm.objects(ST_PushDailyTask.self).filter("status == %d && accountId == %@", ST_FWPushTaskStatus.uploading.rawValue,account.accid).sorted(byKeyPath: "time", ascending: false).first
        
        if let reTask = resumeTask  {
            
            push_task(reTask)
            
            return
        }
        
//        2. 再查询新的任务
        let willPush = realm.objects(ST_PushDailyTask.self).filter("status == %d && accountId == %@", ST_FWPushTaskStatus.normal.rawValue,account.accid).sorted(byKeyPath: "time", ascending: false).first
        
        guard let task = willPush else { return }
        
        push_task(task)
    }
    

//    MARK: - private Method
    fileprivate func push_task(_ task:ST_PushDailyTask){
        
        current_task_i_d = task.id
        
        let realm = try! Realm()
        
        if task.statusEnum == .normal{
            
            try! realm.write {
                task.statusEnum = .uploading
            }
        }
        
        if task.videoPath != ""{
            self.upload_video(task: task)
        }else if task.resources.count > 0{
            self.uploadImage(task: task)
        }else{
                try! realm.write {
                    task.statusEnum = .success
                }
            
                self.progress_view.start_upload(coverImage: UIImage())
            
                self.push_success_task_to_service(task: task)
        }
        
        
    }
    
    fileprivate func upload_video(task:ST_PushDailyTask){
        
        let taskId =  task.id
        
        guard var coverImgPath = SC.push_peculiarity_directory else { return }
        
        coverImgPath.appendPathComponent(task.coverImagePath)
        
        guard let imgData = try? Data.init(contentsOf: coverImgPath) else{
            
            self.current_task_i_d = nil
            
            let realm = try! Realm()
            
            try! realm.write {
                task.statusEnum = .failure
            }
            
            print("加载本地数据失败!!!")
            
            return
        }
        
        
        guard let converImage = UIImage(data: imgData) else{
        
            print("加载本地 PNG 数据失败!!!")
            
            self.current_task_i_d = nil
            
            let realm = try! Realm()
            
            try! realm.write {
                task.statusEnum = .failure
            }
            
            return
        }
        
        self.progress_view.start_upload(coverImage: converImage)
        
        
        JVUpload(videoPath: task.videoPath, coverImage: imgData, uploadProgress:  { (f) in
            
            
            self.progress_view.upload(progressPercent: f.cgFloat)
            
        },success: { (key0, key1) in
            
            
            
            let realm = try! Realm()
            
            guard let task = realm.objects(ST_PushDailyTask.self).first(where: { (item) -> Bool in
                item.id == taskId
            }) else{
                
                self.current_task_i_d = nil
                
                return
            }
            
            try! realm.write {
                
              
                task.statusEnum = .success
                
                task.videoRemoteURL = key1
                
                task.coverImageRemoteURL = key0
            }
            self.push_success_task_to_service(task: task)
            
            
        },failure: { (code, err) in
            
            print("uploadVideoFileToCloud Error:-",err)
            
            self.current_task_i_d = nil
            
            let realm = try! Realm()
            
            try! realm.write {
                task.statusEnum = .failure
            }
            
        })
    }
    
    /**
     退出登录调用
     */
    func cancelTask()  {
        
//        self.cloudPush?.canclePublish()
        
        self.current_task_i_d = nil
        
        self.progress_view.end_upload_status(.failure,videoId:"")
    }
    
    fileprivate func updateStatus(resourceId:String,taskId:String,status:ST_FWPushTaskStatus){
        
        main_thread_execute {
            
            let realm = try! Realm()
                                    
    //                当前 资源 更新状态
            guard let exTask = realm.objects(ST_PushDailyTask.self).filter("id == %@", taskId).first , let curr = realm.objects(ST_PushDailyTaskResource.self).filter("id == %@", resourceId).first else{
                return
            }
            
            try! realm.write {
                curr.statusEnum = status
            }
            
            if status == .success{
//                查询当前task id 的资源是不是 所有都成功了
                  let list = realm.objects(ST_PushDailyTaskResource.self).filter("taskId == %@ AND status == 2", taskId)
                  
                  if list.count == curr.taskResourceCount{
               
                        try! realm.write {
                            exTask.statusEnum = .success
                        }
                    
                      self.push_success_task_to_service(task: exTask)
                  }
            }
            
            if status == .failure{
           
                    try! realm.write {
                        exTask.statusEnum = .failure
                    }
//                失败一次当前 任务结束
                self.current_task_i_d = nil
            }
            
            
            if status == .uploading{
                try! realm.write {
                    exTask.statusEnum = status
                }
            }
        }
    }
    
//    execute in background thread
    fileprivate func uploadImage(taskResourceID:String){
        
        
        let realm = try! Realm()
        
        guard  let taskResource = realm.objects(ST_PushDailyTaskResource.self).filter("id == %@", taskResourceID).first else{
            self.current_task_i_d = nil
            return
        }
        /**
         这个几个值需要跨线程使用， RealmSwift 的 Object 不能跨线程 ,  所以 用 普通的变量来接受
         */
        let id = taskResource.id
        
        let taskId = taskResource.taskId
        
        let sortInTask = taskResource.sortInTask
        
        let resourceCount = taskResource.taskResourceCount
        
        
        guard let converImage = SDImageCache.shared.imageFromCache(forKey: taskResource.path),let imgData = converImage.tian_uploadImageData() else{
            
            main_thread_execute {
                
                print("加载本地 PNG 数据失败!!!")
                
                self.current_task_i_d = nil
                
                self.updateStatus(resourceId: id, taskId: taskId, status: ST_FWPushTaskStatus.failure)
                
            }
            return
        }
        /*
        guard let coverImgPath = SDImageCache.shared.cachePath(forKey: taskResource.path),let imgData = try? Data.init(contentsOf: URL.init(fileURLWithPath: coverImgPath)),let converImage = UIImage.sd_tz_animatedGIF(with: imgData) else{
            
            main_thread_execute {
                
                print("加载本地 PNG 数据失败!!!")
                
                self.current_task_i_d = nil
                
                self.updateStatus(resourceId: id, taskId: taskId, status: ST_FWPushTaskStatus.failure)
                
            }
            return
        }
        */
        

        if sortInTask == 0{
            self.progress_view.start_upload(coverImage: converImage)
        }
        
        self.updateStatus(resourceId: id, taskId: taskId, status: ST_FWPushTaskStatus.uploading)
        
        JVUpload(fileKey: taskResource.path, data: imgData, uploadProgress: { (f) in
            
            self.progress_view.upload(progressPercent: f.cgFloat, currIdx: sortInTask, count: resourceCount)
            
        }, success: { (json) in
            
           self.updateStatus(resourceId: id, taskId: taskId, status: ST_FWPushTaskStatus.success)
            
        }) { (code, err) in
            
            self.updateStatus(resourceId: id, taskId: taskId, status: ST_FWPushTaskStatus.failure)
        }
        
        
    }
    
    fileprivate func uploadImage(task:ST_PushDailyTask){
        
        for item in task.resources {
        
            let id = item.id
            
            back_thread_execute {

                self.uploadImage(taskResourceID: id)
                
            }
        }
    }
    
    
    
    fileprivate func push_success_task_to_service(task:ST_PushDailyTask){
        
        
        var param = ["daily_id":task.dailyId,
                     "remark":task.remark] as [String:Any]
        
        var json_array = [[String : Any]]()
        
//        视频
        if task.videoPath != ""{
            
            param.updateValue(1, forKey: "type")
            
            let detail = ["video_full_duration":task.videoDuration,
                          "video_url":task.videoRemoteURL,
                          "content":task.coverImageRemoteURL,
                          "width":task.imageWidth,
                          "height":task.imageHeight] as [String : Any]
            
            json_array.append(detail)
            
        }
//        图片
        else if task.resources.count > 0{
            
            param.updateValue(2, forKey: "type")
            
            for item in task.resources{
                
                let detail = ["content":item.path,
                              "width":item.imageWidth,
                              "height":item.imageHeight] as [String : Any]
                
                json_array.append(detail)
            }
        }else{
            param.updateValue(3, forKey: "type")
        }
        
        if json_array.count > 0{
            
            let json = JSON(json_array)
            
            param.updateValue(json.rawString() ?? "", forKey: "details")
        }
        
        
        
        print("发布日常:",param)
        
        JVrequest(PH.pushDailyApi, parameters:param,success: { (json) in
            
            ST_BTGlobalDataCenter.shared.pushDailySuccessEvent(dailyType: task.dailyName,daily_id:json["data"].stringValue)
            
            
            
            print("发布日常---:\(json.rawString() ?? "空")")
            
//            NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: MyUserInfoUpdatedNotificationKey), object: nil)
            
            if self.current_task_i_d == task.id{
                
                self.current_task_i_d = nil
            }
            
            let realm = try! Realm()
            
            try! realm.write {
                task.statusEnum = .success
            }
            
            self.progress_view.isHidden = false
            
            self.progress_view.end_upload_status(task.statusEnum,videoId:json["data"]["video_id"].stringValue)
            
            
            NotificationCenter.default.post(name: Notification.Name.push_peculiarity_success, object: nil)
            
            
        }) { (code, err) in
            
            print("uploadFileToTXCloud push Error:-",err)
            
                self.current_task_i_d = nil
            
            let realm = try! Realm()
            
            try! realm.write {
                task.statusEnum = .failure
            }
            
            self.progress_view.end_upload_status(task.statusEnum,videoId:"")
            
        }
    }
    
    
}

/*
extension ST_PushDailyCoordinator:TXVideoPublishListener{
    
    
    func onPublishProgress(_ uploadBytes: Int, totalBytes: Int) {
        
        print("日常 腾讯云上传进度：",uploadBytes," 总进度:",totalBytes)
        
        self.progress_view.upload(progressPercent: uploadBytes.cgFloat/totalBytes.cgFloat)
        
    }
    
    func onPublishComplete(_ result: TXPublishResult!) {
        
        print("日常 腾讯云上传完成 retCode：",result.retCode,"--descMsg:",result.descMsg ?? "🈚️")
        
        guard let taskId = current_task_i_d else { return  }
        
        main_thread_execute {
            
            let realm = try! Realm()
            
            guard let task = realm.objects(ST_PushDailyTask.self).first(where: { (item) -> Bool in
                item.id == taskId
            }) else{
                
                self.current_task_i_d = nil
                
                return
            }
            
            try! realm.write {
                
                if result.retCode == 0 {
                    
                    task.statusEnum = .success
                    
                    task.videoRemoteURL = result.videoURL ?? ""
                    task.coverImageRemoteURL = result.coverURL ?? ""
                }else{
                    
                    task.statusEnum = .failure
                }
            }
            self.push_success_task_to_service(task: task)
            
            
        }
    }
    
}
*/




//MARK: - Model
class ST_PushDailyTask: Object {
    
    @objc dynamic  var id = UUID().uuidString
    
    @objc dynamic  var dailyId = ""
    
    @objc dynamic  var dailyName = ""
    
    @objc dynamic  var accountId = ""
    
    @objc dynamic  var remark = ""
    
    @objc dynamic  var time = Date()
    
    @objc dynamic var status = ST_FWPushTaskStatus.normal.rawValue
    
    var statusEnum: ST_FWPushTaskStatus {
        get { return ST_FWPushTaskStatus(rawValue: status)! }
        set { status = newValue.rawValue }
    }
    
//    如果是视频
    @objc dynamic  var videoPath = ""
    
    @objc dynamic  var coverImagePath = ""
    
    @objc dynamic  var imageWidth = 0.0
    
    @objc dynamic  var imageHeight = 0.0
    
    @objc dynamic  var videoDuration = 0
//    如果是图片
    let resources = List<ST_PushDailyTaskResource>()
    
//    MARK: push param
    @objc dynamic  var comments = ""
    
    @objc dynamic  var videoRemoteURL = ""
    
    @objc dynamic  var coverImageRemoteURL = ""
    
    

}



/**
 发布图片使用
 */
class ST_PushDailyTaskResource: Object {
    
    @objc dynamic  var id = UUID().uuidString
    
    @objc dynamic  var taskId = ""
    
    @objc dynamic  var taskResourceCount = 1
    
    @objc dynamic  var path = ""
//    当前这一组图片 排序 升序 [0,1,2...]
    @objc dynamic  var sortInTask = 0
    
    @objc dynamic  var imageWidth = 0.0
    
    @objc dynamic  var imageHeight = 0.0
    
    @objc dynamic var status = ST_FWPushTaskStatus.normal.rawValue
    
    var statusEnum: ST_FWPushTaskStatus {
        get { return ST_FWPushTaskStatus(rawValue: status)! }
        set { status = newValue.rawValue }
    }
    
//    直接生成 远程 image key  弃用使用 path 字段代替 example CAE7F9D7-BD21-4885-910B-EB5F0804DEFFzzz.png
    @objc dynamic  var remoteURL = UUID().uuidString
    
}
